# -*- coding: utf-8 -*-
import sys
import os
import io
import chardet
import win32com.client as win32
from playwright.sync_api import Playwright, sync_playwright, expect

import usage_logger
import json
from user_data import send_monitoring_data

# 读取manifest.json中的版本信息
def get_version():
    try:
        # 获取当前脚本所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        manifest_path = os.path.join(current_dir, 'manifest.json')
        
        with open(manifest_path, 'r', encoding='utf-8') as f:
            manifest_data = json.load(f)
            return manifest_data.get('version', '1.0.0')
    except Exception as e:
        print(f"⚠️ 读取版本信息失败: {str(e)}")
        return '1.0.0'  # 默认版本

# 设置标准输出和错误输出的编码为UTF-8
if sys.platform == "win32":
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')


def clear_txt():
    """清空日志文件"""
    script_dir = os.path.dirname(os.path.abspath(__file__))
    error_file = os.path.join(script_dir, "BO_Input_error.txt")
    log_file = os.path.join(script_dir, "BO_Input_log.txt")
    
    with open(error_file, "w") as file:
        pass
    with open(log_file, "w") as file:
        pass


def append_error(error_message):
    """追加报错信息"""
    script_dir = os.path.dirname(os.path.abspath(__file__))
    error_file = os.path.join(script_dir, "BO_Input_error.txt")
    with open(error_file, "a", encoding="utf-8") as file:
        file.write(error_message + "\n")


def append_log(log_message):
    """追加日志信息"""
    script_dir = os.path.dirname(os.path.abspath(__file__))
    log_file = os.path.join(script_dir, "BO_Input_log.txt")
    with open(log_file, "a", encoding="utf-8") as file:
        file.write(log_message + "\n")


def main(excel_file_path, bo_address=None, default_timeout=None, timeout=None, username=None, password=None, headless=True):
    """主函数"""
    clear_txt()
    # 输出开始信息到日志
    print("=== BO Input 自动化脚本开始执行 ===")
    print(f"浏览器模式: {'后台运行' if headless else '显示浏览器'}")

    # 使用传入的参数或默认值
    config_params = {
        'BO_Address': bo_address or 'https://cnapp.sgs.net/backoffice/user/login.htm',
        'defaultTimeout': default_timeout or 6000,
        'timeout': timeout or 500,
        'userName': username or '',
        'passWord': password or ''
    }
    
    # 验证文件路径
    if not excel_file_path:
        print("错误：未提供Excel文件路径")
        return
    
    print(f"接收到的文件路径: {excel_file_path}")
    
    # 检查文件是否存在
    if not os.path.exists(excel_file_path):
        print(f"错误：文件不存在 - {excel_file_path}")
        # 尝试检查当前工作目录
        current_dir = os.getcwd()
        print(f"当前工作目录: {current_dir}")
        # 检查是否是相对路径问题
        if not os.path.isabs(excel_file_path):
            abs_path = os.path.abspath(excel_file_path)
            print(f"尝试绝对路径: {abs_path}")
            if os.path.exists(abs_path):
                excel_file_path = abs_path
                print(f"使用绝对路径: {excel_file_path}")
            else:
                return
        else:
            return
    
    # 检查文件扩展名
    if not excel_file_path.lower().endswith(('.xlsx', '.xls')):
        print(f"错误：不支持的文件格式 - {excel_file_path}")
        return
    
    # 转换为绝对路径
    file_path = os.path.abspath(excel_file_path)
    print(f"使用Excel文件: {file_path}")
    
    # Excel操作
    excel = None
    workbook = None
    try:
        excel = win32.gencache.EnsureDispatch('Excel.Application')
        excel.DisplayAlerts = False
        excel.Visible = False
        
        # 尝试打开Excel文件
        try:
            workbook = excel.Workbooks.Open(file_path, ReadOnly=True)
        except Exception as e:
            print(f"错误：无法打开Excel文件 - {str(e)}")
            if "找不到" in str(e) or "cannot find" in str(e).lower():
                print(f"请检查文件路径是否正确：{file_path}")
            return
            
        sheet = workbook.Worksheets(1)
        last_row = sheet.Cells(sheet.Rows.Count, 1).End(win32.constants.xlUp).Row

        # Playwright操作
        with sync_playwright() as p:
            browser = p.chromium.launch(
                executable_path=r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
                headless=headless,
                args=['--window-size=1366,768']
            )

            contexts = browser.contexts
            context = browser.new_context(no_viewport=True)
            page = context.new_page()

            # 登录
            page.goto(config_params['BO_Address'])
            page.set_default_timeout(config_params['defaultTimeout'])
            page.get_by_placeholder("Username").fill("APAC\\" + config_params['userName'])
            page.get_by_placeholder("Password").fill(config_params['passWord'])
            page.get_by_role("button", name="Login").click()

            # 进入菜单
            page.locator("a").filter(has_text="INV2FP Management").click()
            page.wait_for_timeout(config_params['timeout'])
            page.wait_for_selector('span:has-text("Ready for Confirmation")').click()
            page.wait_for_timeout(config_params['timeout'])
            page.locator("a").filter(has_text="General").nth(0).click()

            # 处理单据
            for i in range(2, last_row + 1):
                invoice_No = sheet.Cells(i, 1).Value
                invoice_No = int(invoice_No)
                email = sheet.Cells(i, 7).Value.replace(' ', '')
                F_code = sheet.Cells(i, 11).Value
                invoice_type = sheet.Cells(i, 18).Value
                payer_name = sheet.Cells(i, 5).Value
                print(f"📋 正在处理 - 发票号: {invoice_No}")

                # 构造监控数据
                data = [
                    {
                        "user_name": f"{usage_logger.username}",
                        "user_location": f"{usage_logger.location}",
                        "rpa_id": "123",
                        "rpa_name": "BO_Input",
                        "rpa_version": get_version(),
                        "occurrence": f"{usage_logger.start_time}",
                        "info": "BO系统自动录入数据",
                        "extra": f"{invoice_No}",
                    }
                ]
                
                if '；' in email:
                    email = email.replace('；', ';')
                if '，' in email or ',' in email:
                    email = email.replace('，', ';').replace(',', ';')
                if '@' not in email or email.count('@') > 4 or email.count(
                        ';') > 3 or email == '' or email is None or '>' in email or '<' in email:
                    append_error(f"{invoice_No}邮箱错误")
                    continue
                
                try:
                    # 等待页面完全加载
                    page.wait_for_timeout(2000)
                    
                    # 等待元素可见并点击
                    org_code_selector = page.locator('#select2-initOrgCode-container')
                    org_code_selector.wait_for(state='visible', timeout=10000)
                    org_code_selector.click()
                    
                    # 填写搜索内容
                    search_input = page.locator('//input[@type="search" and @role="textbox"]')
                    search_input.wait_for(state='visible', timeout=5000)
                    search_input.fill(F_code)
                    
                    page.locator('//ul[@role="tree"]/li[1]').click()
                    page.locator("#invoiceNumber").fill(str(invoice_No))
                    page.get_by_role("button", name="Search").click()
                    page.locator("//li[@id='Complete']").click()
                    page.locator('//*[@id="invoice_confirm_list"]/tbody/tr[2]/td[3]/a/span').click()  # 点+
                    page.get_by_role("button", name="Edit").click()
                    page.wait_for_timeout(config_params['timeout'])
                    input_email_selector = 'input[placeholder="多个邮箱地址，请使用半角分号隔开"]'
                    
                    # 判断invoice_type并选择
                    if invoice_type == '纸质专用发票':
                        # 直接通过ID定位下拉菜单，ID格式为SELECTED+数字
                        # 查找所有以SELECTED开头的select元素
                        select_elements = page.locator('select[id^="SELECTED"]')
                        if select_elements.count() > 0:
                            # 选择第一个匹配的select元素
                            invoice_type_select = select_elements.first
                            invoice_type_select.select_option('Special-E')
                            print(f"✅ 已修改为电子专用发票")
                        else:
                            print(f"❌ 纸质发票未修改成功")
                        
                        # 填写邮箱
                        page.locator(input_email_selector).first.click()
                        page.locator(input_email_selector).first.fill(str(email))
                        page.get_by_role("button", name="Save and Confirm").click()
                        page.get_by_role("button", name="OK").click()
                        print(f"✅ {invoice_No}完成，{payer_name} 是纸质专用发票！")
                        send_monitoring_data(data)
                        page.locator("#label_collapse").click()
                    else:
                        # 通过父元素的XPath定位父元素
                        page.locator(input_email_selector).first.click()
                        page.locator(input_email_selector).first.fill(str(email))
                        page.get_by_role("button", name="Save and Confirm").click()
                        page.get_by_role("button", name="OK").click()
                        print(f"✅ {invoice_No}完成！")
                        send_monitoring_data(data)
                        page.locator("#label_collapse").click()
                        
                except TimeoutError:
                    print(f"❌ 单号：{invoice_No}失败，查询超时！")
                    continue
                except Exception as e:
                    print(f"❌ 单号：{invoice_No}失败，{str(e)}")
                    continue
            
            context.close()
            browser.close()
            print('运行结束！')
    except Exception as e:
        print(f"脚本执行出错: {str(e)}")
    finally:
        # 清理Excel资源
        try:
            if workbook:
                workbook.Close(SaveChanges=False)
            if excel:
                excel.Quit()
        except Exception as e:
            print(f"清理Excel资源时出错: {str(e)}")


if __name__ == "__main__":
    """命令行入口点"""
    if len(sys.argv) > 1:
        excel_path = sys.argv[1]
        # 支持从命令行传递配置参数（JSON格式）
        if len(sys.argv) > 2:
            try:
                config_json = sys.argv[2]
                config_data = json.loads(config_json)
                main(excel_path, 
                     bo_address=config_data.get('boAddress'),
                     default_timeout=config_data.get('defaultTimeout'),
                     timeout=config_data.get('timeout'),
                     username=config_data.get('username'),
                     password=config_data.get('password'),
                     headless=config_data.get('headless', True))
            except json.JSONDecodeError:
                print("错误：配置参数格式不正确")
                sys.exit(1)
        else:
            main(excel_path)
    else:
        print("错误：请提供Excel文件路径作为命令行参数")
        print("使用方法: python BO_Input.py <excel_file_path> [config_json]")
        sys.exit(1)